import serial
import time
import sys
import re

# 定义常量
DEBUG_PORT = "COM4"
BAUDRATE = 115200

# 定义变量
debug_serial = None
runTimes = 1
timeout = 500  # 超时设置为500秒

# log文件
DEBUG_LOG = ""


# 检查端口连接状态，传入端口，返回串口对象
def check_port_status(COM_PORT):
    try:
        debug_serial = serial.Serial(COM_PORT, BAUDRATE)
    except Exception as e:
        print("debug口连接失败，请检查端口", e)
        sys.exit()
    return debug_serial


# 创建log文件夹
def creat_log_file():
    global DEBUG_LOG
    DEBUG_LOG = "DEBUG_LOG_{}.log".format(
        time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime())
    )


# 发送COM口指令，可以向AT口和debug发送指令
def at_write(command, timeout, at_port_opened, at_result, RDY=0, CPIN=0):
    at_command = command.encode("UTF-8")
    at_port_opened.write(at_command)


# 读取COM口返回值
def at_read(serial_port, logFile=""):
    rec_str = ""
    while True:
        time.sleep(1)
        lenth = serial_port.inWaiting()
        if lenth > 0:
            rec_str = serial_port.read(size=lenth)
            # print("rec_str",rec_str)
            try:
                rec_str = re.sub("\\x1b.*?m", "", rec_str.decode("UTF-8"), 0, re.I)
                if logFile != "":
                    with open(logFile, "a") as file_object:
                        file_object.write(
                            str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
                            + "\r\n"
                            + rec_str
                            + "\r\n"
                        )
                return rec_str
            except:
                return ""
        else:
            break

    return rec_str


# log写入函数
def write_log(log, logFile=""):
    with open(logFile, "a") as file_object:
        file_object.write(
            str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
            + "\r\n"
            + log
            + "\r\n"
        )
        print(log)


def write_run_times():
    global runTimes

    with open(DEBUG_LOG, "a") as file_object:
        file_object.write(
            "{} runTimes : {} {}\r\n{}\r\n".format(
                "<" * 20,
                runTimes,
                ">" * 20,
                time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime()),
            )
        )
    runTimes += 1


# debug口登录模块
def login_device():
    global DEBUG_LOG
    # 确认登录失败的条件，或者，不可能失败
    while True:
        print("等待登录... ... ")
        time.sleep(3)
        at_write("\r\n", 3, debug_serial, "OK")
        result = at_read(debug_serial)

        with open(DEBUG_LOG, "a") as file_object:
            file_object.write(result)

        if "login:" in result:
            at_write("root\r\n", 3, debug_serial, "OK")
            print("账号输入成功")
            time.sleep(2)
            at_write("oelinux123\r\n", 3, debug_serial, "OK")
            print("密码输入成功")
        elif "~ # oelinux123" in result or (
            "\r\n~ # \r\n~ #" in result
            and "sys_reboot" not in result
            and "fotainfo --get-all" not in result
        ):
            print("登录成功")
            at_write("echo 2 >/proc/sys/kernel/printk\r\n", 3, debug_serial, "OK")
            at_read(debug_serial)
            break


def into_app():
    # os.popen("adb shell rm -rf /data/*.pcm")
    # time.sleep(2)
    # at_write("-1\r\n", 3, debug_serial, "OK")
    # at_write("-1\r\n", 3, debug_serial, "OK")
    at_write("cd /data\r\n", 3, debug_serial, "OK")
    # at_write("rm -rf *.pcm\r\n", 3, debug_serial, "OK")
    time.sleep(2)
    at_write("./test_sdk_api*\r\n", 3, debug_serial, "OK")
    at_write("7\r\n", 3, debug_serial, "OK")
    # 初始化audio接口
    at_write("0\r\n", 3, debug_serial, "OK")
    init_value = at_read(debug_serial, DEBUG_LOG)
    if "dm init ok" in init_value:
        write_log("dm初始化成功,PASS", DEBUG_LOG)
    else:
        write_log("dm初始化完成,PASS", DEBUG_LOG)


def set_qmssr_3():
    # ql_audio_playback_pause 暂停播放音频
    at_write("27\n3\n", 3, debug_serial, "OK")
    capture_value = at_read(debug_serial, DEBUG_LOG)
    if "ql_dm_set_mssr_level to 3" in capture_value:
        write_log("设置ql_dm_set_mssr_level to 3成功", DEBUG_LOG)
        # state_value = playback_state()
        # if "state = 5" in state_value:
        #     write_log("audio播放状态正确，PASS", DEBUG_LOG)
    else:
        write_log("设置ql_dm_set_mssr_level to 3错误，FAIL", DEBUG_LOG)
        sys.exit()
    at_write("-1\r\n", 3, debug_serial, "OK")


# 新增sdk api拨号
def set_netcall():
    at_write("0\r\n", 3, debug_serial, "OK")
    time.sleep(2)
    at_write("0\r\n", 3, debug_serial, "OK")
    ql_data_call_init = at_read(debug_serial, DEBUG_LOG)
    if "Successful" not in ql_data_call_init:
        write_log("ql_data_call_init错误，FAIL", DEBUG_LOG)
        sys.exit()
    time.sleep(2)
    at_write("1\n1\nsd\n0\n", 3, debug_serial, "OK")
    ql_data_call_create = at_read(debug_serial, DEBUG_LOG)
    if "Successful" not in ql_data_call_create:
        write_log("ql_data_call_create错误，FAIL", DEBUG_LOG)
        sys.exit()
    time.sleep(2)
    at_write("2\n1\n1\n1\n1\n\ny\n", 3, debug_serial, "OK")
    ql_data_call_config = at_read(debug_serial, DEBUG_LOG)
    if "Successful" not in ql_data_call_config:
        write_log("ql_data_call_config错误，FAIL", DEBUG_LOG)
        sys.exit()
    time.sleep(3)
    at_write("9\n", 3, debug_serial, "OK")
    ql_data_call_set_status_ind_cb = at_read(debug_serial, DEBUG_LOG)
    if "Successful" not in ql_data_call_set_status_ind_cb:
        write_log("ql_data_call_set_status_ind_cb错误，FAIL", DEBUG_LOG)
        sys.exit()
    time.sleep(3)
    at_write("4\n1\n", 3, debug_serial, "OK")
    ql_data_call_start = at_read(debug_serial, DEBUG_LOG)
    if "call_status=CONNECTED" in ql_data_call_start:
        write_log("create netcall成功", DEBUG_LOG)
    else:
        write_log("create netcall fail!!!", DEBUG_LOG)
        print("create netcall fail!!!")
        sys.exit()
    at_write("-1\r\n", 3, debug_serial, "OK")


def set_modem_restart(max_duration=60):
    at_write("7\r\n", 3, debug_serial, "OK")
    at_write("0\r\n", 3, debug_serial, "OK")
    at_write("28\r\n", 3, debug_serial, "OK")

    start_time = time.time()  # 记录开始时间
    while True:
        elapsed_time = time.time() - start_time
        if elapsed_time > max_duration:
            print("超时，未检测到拨号成功，退出循环")
            sys.exit()  # 强制退出循环
        time.sleep(1)
        capture_value = at_read(debug_serial, DEBUG_LOG)
        # print("capture_value:", capture_value)  # 调试输出
        # 提取成功数据和其前一个事件
        reconnect_data, successful_data = extract_call_status_with_context(
            capture_value
        )

        if successful_data:
            # 直观展示拨号成功和重连数据
            display_call_status(reconnect_data, successful_data)
            return
        else:
            print("未检测到拨号成功状态，继续等待...")


def display_call_status(reconnect_data, successful_data):
    """
    将拨号数据以直观方式打印。
    """
    if reconnect_data:
        print("\n===== 重连数据 =====")
        for key, value in reconnect_data.items():
            print(f"{key:<25}: {value}")
    else:
        print("\n===== 重连数据 =====")
        print("无有效重连数据")

    if successful_data:
        print("\n===== 拨号成功数据 =====")
        for key, value in successful_data.items():
            print(f"{key:<25}: {value}")
    else:
        print("\n===== 拨号成功数据 =====")
        print("无有效拨号成功数据")


def extract_call_status_with_context(capture_value):
    """
    提取 capture_value 中拨号成功数据和其前一个事件（重连数据）。
    """
    all_results = []
    capture_lines = capture_value.splitlines()  # 按行分割 capture_value

    current_result = {}
    for line in capture_lines:
        line = line.strip()
        if line.startswith("----DATA CALL STATUS CHANGE EVENT:"):
            # 如果遇到新的事件，保存当前结果并重新初始化
            if current_result:
                all_results.append(current_result)
                current_result = {}
        elif "=" in line:  # 提取键值对
            try:
                key, value = line.split("=", 1)
                key = key.strip()
                value = value.strip()
                current_result[key] = value
            except ValueError:
                continue  # 跳过解析失败的行
    # 保存最后一个事件
    if current_result:
        all_results.append(current_result)

    # 查找拨号成功的数据和其前一个事件
    for i in range(1, len(all_results)):
        result = all_results[i]
        if (
            result.get("call_end_reason_type") == "0"
            and result.get("call_end_reason_code") == "0x0"
        ):
            reconnect_data = all_results[i - 1]  # 成功数据的上一个事件
            return reconnect_data, result

    return None, None  # 如果没有成功数据，返回 None


debug_serial = check_port_status(DEBUG_PORT)
creat_log_file()
login_device()
into_app()
time.sleep(2)
set_qmssr_3()
time.sleep(2)
set_netcall()
while True:
    write_run_times()
    time.sleep(2)
    set_modem_restart()
